#pragma once

#include "DataInterfaceTypeInfo_h.h"

#include "OpcDefs.h"

#include <map>
#include <string>
#include <sstream>
#include <boost/thread/mutex.hpp>
#include <boost/thread.hpp>

//using namespace boost::algorithm;


using std::map;
using std::wstring;
using boost::shared_mutex;
using std::wstringstream;

struct tag_state_sync_t: tag_state_t {
	tag_state_sync_t(const tag_state_sync_t& another) 
		: tag_state_t(dynamic_cast<const tag_state_t&>(another))
	{	}
	tag_state_sync_t() {};
	shared_mutex access_mutex;
};

extern map<unsigned, tag_state_sync_t> g_tag_values; 
extern shared_mutex g_tag_values_mutex;
extern unsigned data_interface_count;

inline tag_config_t parse_tag_config_string(const wstring& tag_config_string) {
	tag_config_t tag_config;

	const wchar_t* ptr = tag_config_string.c_str() + tag_config_string.size();
	while (*(--ptr) != L'\t') {
	}
	tag_config.opc_path = const_cast<wchar_t *> (ptr + 1);

	wstringstream wss(tag_config_string);
	wss >> tag_config.tag_id;
	wss >> tag_config.vt;
	unsigned opc_access;
	wss >> opc_access;
	tag_config.opc_access = static_cast<tag_opc_access_t>(opc_access);

	return tag_config;
}

class DataInterface : 
	public IDataInterface
{
public:
	OPC_CLASS_NEW_DELETE()

	DataInterface();
	virtual ~DataInterface();

	// IUnknown
	STDMETHODIMP QueryInterface(REFIID riid, void** pIFace);
	STDMETHODIMP_(DWORD)AddRef();
	STDMETHODIMP_(DWORD)Release();

	
	//typedef HRESULT (__stdcall PfnOpcCreateInstance)(IUnknown**, const CLSID*);
	typedef HRESULT (__stdcall PfnOpcCreateInstance)(IUnknown**, const CLSID*);

	static unsigned instance_count();
	static STDMETHODIMP CreateInstance(IUnknown** ppv, const CLSID* clsid);

    virtual HRESULT STDMETHODCALLTYPE Configure( 
        /* [in] */ long configuration_size,
		/* [size_is][in] */ tag_config_t configuration[  ]
		);

    virtual HRESULT STDMETHODCALLTYPE AddTag(
        /* [in] */ tag_config_t configuration,
        /* [in]  */ BOOL last_tag
        );

    
    virtual HRESULT STDMETHODCALLTYPE Write( 
        /* [in] */ long value_count,
        /* [size_is][in] */ tag_value_t values[  ]);

    virtual HRESULT STDMETHODCALLTYPE Read( 
        /* [in] */ unsigned int value_count,
        /* [size_is][out][in] */ tag_value_t values[  ]);

private:
	
	DWORD	m_refCount;
	double  data_;
};
